#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "wiringSerial.h"

//打开并初始化串口设备
int myserialOpen (const char *device, const int baud)
{
    struct termios options ;    //串口配置选项结构体
    speed_t myBaud ;            //波特率变量
    int status, fd ;            //状态和文件描述符

    //根据传入的波特率设置对应的系统波特率常量
    switch (baud){
        case 9600: myBaud = B9600 ; break ;
        case 115200: myBaud = B115200 ; break ;
    } 

    //以读写、非阻塞方式打开串口设备
    if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
    return -1 ;

    fcntl (fd, F_SETFL, O_RDWR) ;//设置文件状态标志

    // Get and modify current options:

    //获取并修改当前串口选项
    tcgetattr (fd, &options) ;  //

    cfmakeraw (&options) ;      //设置为原始模式
    cfsetispeed (&options, myBaud) ;    //设置输入波特率
    cfsetospeed (&options, myBaud) ;    //设置输出波特率

    //配置串口参数
    options.c_cflag |= (CLOCAL | CREAD) ;   //启用接收器，本地连接
    options.c_cflag &= ~PARENB ;            //无奇偶校验
    options.c_cflag &= ~CSTOPB ;            //1个停止位
    options.c_cflag &= ~CSIZE ;             //清楚数据为设置
    options.c_cflag |= CS8 ;                //8个数据位置
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;//非规范模式
    options.c_oflag &= ~OPOST ;             //禁用输出处理

    //设置最小字符数和超时时间
    options.c_cc [VMIN] = 0 ;   //最小字符数为0
    options.c_cc [VTIME] = 100 ; // 超时时间10秒（100 deciseconds）

    tcsetattr (fd, TCSANOW,&options);   //立即应用设置
    ioctl (fd, TIOCMGET, &status);  //获取当前串口状态  
    
    //设置DTR和RTS信号线
    status |= TIOCM_DTR ;
    status |= TIOCM_RTS ;

    ioctl (fd, TIOCMSET, &status);//应用串口状态设置

    usleep (10000) ; // 延时10mS等待串口稳定

    return fd ; //返回串口文件描述符
}

//通过串口发送数据
//传递的 数据帧 格式 0XAA 0X55 0X46 0x00 0X55 0XAA
void serialSendstring (const int fd, const unsigned char *s, int len)
{
    int ret;
    //注意：使用strlen(s)可能会导致数据长度缺失，因为二进制数据中可能包含0x00
    ret = write (fd, s, len);//向串口写入数据
    if (ret < 0)
        printf("Serial Puts Error\n");//写入失败打印错误消息
}

//从串口读取数据
int serialGetstring (const int fd, unsigned char *buffer)
{
    int n_read;

    n_read = read(fd, buffer,32);//从串口读取最大32个字节的数据

    return n_read; //返回实际读取的字节数
}